 /*
  * Copyright (c) 2021, 2023, yishun.cn All rights reserved.
  *
  */
 package com.hmdp.utils;

 import cn.hutool.core.lang.UUID;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.core.io.ClassPathResource;
 import org.springframework.data.redis.core.StringRedisTemplate;
 import org.springframework.data.redis.core.script.DefaultRedisScript;

 import java.util.Collections;
 import java.util.concurrent.TimeUnit;


 /**
  * <p>Project: hm-dianping-com.hmdp.utils-SimpleRedisLock
  * <p>Powered by yishun On 2023-03-20 22:28:26
  *
  * @author yishun [2465734101@qq.com]
  * @version 1.0
  * @since 17
  */
 public class SimpleRedisLock implements ILock {

     private String name;
     private StringRedisTemplate stringRedisTemplate;
     private static final String KEY_PREFIX = "lock:";
     public static final String ID_PREFIX = UUID.randomUUID().toString(true) + "-";
     //定义锁的脚本
     public static final DefaultRedisScript<Long> UNLOCK_SCRIPT;

     static {
         UNLOCK_SCRIPT = new DefaultRedisScript<>();
         UNLOCK_SCRIPT.setLocation(new ClassPathResource("unlock.lua"));
         UNLOCK_SCRIPT.setResultType(Long.class);
     }

     public SimpleRedisLock(String name, StringRedisTemplate stringRedisTemplate) {
         this.name = name;
         this.stringRedisTemplate = stringRedisTemplate;
     }

     @Override
     public boolean tryLock(long timeoutSec) {
         //获取线程标识
         String threadId = ID_PREFIX + Thread.currentThread().getId();
         //获取锁
         Boolean success = stringRedisTemplate.opsForValue().setIfAbsent(KEY_PREFIX + name, threadId, timeoutSec, TimeUnit.SECONDS);
         return Boolean.TRUE.equals(success);//避免拆箱空指针
     }


     @Override
     public void unlock() {
         stringRedisTemplate.execute(
                 UNLOCK_SCRIPT,
                 Collections.singletonList(KEY_PREFIX + name),
                 ID_PREFIX + Thread.currentThread().getId()
         );
     }

     /*@Override
     public void unlock() {
         //获取线程标识
         String threadId = ID_PREFIX + Thread.currentThread().getId();
         //获取锁中的标识
         String id=stringRedisTemplate.opsForValue().get(KEY_PREFIX + name);
         //判断标识是否一致，防止误删
         if(threadId.equals(id)){
             //释放锁
             stringRedisTemplate.delete(KEY_PREFIX + name);
         }
     }*/
 }
